//
//  SampleHeartRateAppViewController.m
//  SampleHeartRateApp
//
//  Created by Chris Greening on 25/11/2010.
//  Copyright 2010 CMG Research. All rights reserved.
//

#import "SampleHeartRateAppViewController.h"

@implementation SampleHeartRateAppViewController

@synthesize simpleChart;



/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/

-(void)proximitySensorChange:(NSNotification*)not{
    NSLog(@"距离发生搞边：%d",[UIDevice currentDevice].proximityState);
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

  self.title = @"心率检测";
    // 添加通知
    [[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
    if ([UIDevice currentDevice].proximityMonitoringEnabled == YES)
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(proximitySensorChange:)
                                                     name:UIDeviceProximityStateDidChangeNotification
                                                   object:nil];

	// start capturing frames
	// Create the AVCapture Session
	session = [[AVCaptureSession alloc] init];
	
	// create a preview layer to show the output from the camera
	//	AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
	//	previewLayer.frame = previewView.frame;
	//	[previewView.layer addSublayer:previewLayer];
	
	// Get the default camera device
	AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//	if([camera isTorchModeSupported:AVCaptureTorchModeOn]) {
//		[camera lockForConfiguration:nil];
//		camera.torchMode=AVCaptureTorchModeOn;
//		//	camera.exposureMode=AVCaptureExposureModeLocked;
//		[camera unlockForConfiguration];
//	}
	// Create a AVCaptureInput with the camera device
	NSError *error=nil;
	AVCaptureInput* cameraInput = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&error];
	if (cameraInput == nil) {
		NSLog(@"Error to create camera capture:%@",error);
	}
	
	// Set the output
	AVCaptureVideoDataOutput* videoOutput = [[AVCaptureVideoDataOutput alloc] init];
	
	// create a queue to run the capture on
	dispatch_queue_t captureQueue=dispatch_queue_create("catpureQueue", NULL);
	
	// setup our delegate
	[videoOutput setSampleBufferDelegate:self queue:captureQueue];
	
	// configure the pixel format
	videoOutput.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey,
															 nil];
	// and the size of the frames we want
	[session setSessionPreset:AVCaptureSessionPresetLow];
	
	// Add the input and output
  if (cameraInput) {
    [session addInput:cameraInput];
  }
  if (videoOutput) {
    [session addOutput:videoOutput];
  }
	
    
    simpleChart.delegate = self;
	// Start the session
//	[session startRunning];		
}

// r,g,b values are from 0 to 1 // h = [0,360], s = [0,1], v = [0,1] 
//	if s == 0, then h = -1 (undefined) 
void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ) {
	float min, max, delta; 
	min = MIN( r, MIN(g, b )); 
	max = MAX( r, MAX(g, b )); 
	*v = max;
	delta = max - min; 
	if( max != 0 )
		*s = delta / max;
	else {
		// r = g = b = 0 
		*s = 0; 
		*h = -1; 
		return;
	}
	if( r == max )
		*h = ( g - b ) / delta; 
	else if( g == max )
		*h=2+(b-r)/delta;
	else 
		*h=4+(r-g)/delta; 
	*h *= 60;
	if( *h < 0 ) 
		*h += 360;
}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
	static int count=0;
	count++;
	// only run if we're not already processing an image
	// this is the image buffer
	CVImageBufferRef cvimgRef = CMSampleBufferGetImageBuffer(sampleBuffer);
	// Lock the image buffer
	CVPixelBufferLockBaseAddress(cvimgRef,0);
	// access the data
	int width=CVPixelBufferGetWidth(cvimgRef);
	int height=CVPixelBufferGetHeight(cvimgRef);
	// get the raw image bytes
	uint8_t *buf=(uint8_t *) CVPixelBufferGetBaseAddress(cvimgRef);
	size_t bprow=CVPixelBufferGetBytesPerRow(cvimgRef);
	float r=0,g=0,b=0;
	for(int y=0; y<height; y++) {
		for(int x=0; x<width*4; x+=4) {
			b+=buf[x];
			g+=buf[x+1];
			r+=buf[x+2];
			//			a+=buf[x+3];
		}
		buf+=bprow;
	}
	r/=255*(float) (width*height);
	g/=255*(float) (width*height);
	b/=255*(float) (width*height);

	float h,s,v;
	
	RGBtoHSV(r, g, b, &h, &s, &v);
	
	// simple highpass and lowpass filter - do not use this for anything important, it's rubbish...
	static float lastH=0;
	float highPassValue=h-lastH;
	lastH=h;
	float lastHighPassValue=0;
	float lowPassValue=(lastHighPassValue+highPassValue)/2;
	lastHighPassValue=highPassValue;
	
	// send the point to the chart to be displayed
    if (detectionIsStart) {
      @autoreleasepool {
        [simpleChart performSelectorOnMainThread:@selector(addPoint:) withObject:[NSArray arrayWithObjects:[NSNumber numberWithFloat:lowPassValue],[NSNumber numberWithFloat:r],[NSNumber numberWithFloat:g],[NSNumber numberWithFloat:b], nil] waitUntilDone:NO];
      }
    }
}

-(void)viewWillAppear:(BOOL)animated{
  [super viewWillAppear:animated];
  [self.navigationController setNavigationBarHidden:NO animated:YES];
}

-(void)viewWillDisappear:(BOOL)animated{
  [super viewWillDisappear:animated];
  [self.navigationController setNavigationBarHidden:YES animated:YES];
}


/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren't in use.
}


-(IBAction)controlBtnClick:(id)sender{
    detectionIsStart = !detectionIsStart;
    AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
	if([camera hasTorch]) {
        if (!detectionIsStart) {
            [session stopRunning];
            [stopBtn setTitle:@"开始" forState:UIControlStateNormal];
            [camera lockForConfiguration:nil];
            camera.torchMode=AVCaptureTorchModeOff;
            [camera unlockForConfiguration];
        }else{
            [simpleChart clearDetectionData];
            [session startRunning];
            [stopBtn setTitle:@"停止" forState:UIControlStateNormal];
            [camera lockForConfiguration:nil];
            camera.torchMode=AVCaptureTorchModeOn;
            [camera unlockForConfiguration];
//            UIRectClip(CGRect rect)
            
        }
		//	camera.exposureMode=AVCaptureExposureModeLocked;
	}
    camera = nil;
}

-(void)detectionFinishNotif{
    [self controlBtnClick:nil];
}


- (void)dealloc {
	self.simpleChart = nil;
    // 移除通知
    if ([UIDevice currentDevice].proximityMonitoringEnabled == YES)
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:UIDeviceProximityStateDidChangeNotification
                                                      object:nil];
    [[UIDevice currentDevice] setProximityMonitoringEnabled:NO];
}

@end
